home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 2
/
Atari Mega Archive CD - Volume 2.iso
/
linux
/
tools
/
gtar10.lha
/
rtape_lib.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-09
|
13KB
|
650 lines
/* Remote tape emulator subroutines.
Copyright (C) 1988 Free Software Foundation
This file is part of GNU Tar.
GNU Tar is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GNU Tar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Tar; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* JF: modified to make all rmtXXX calls into macros for speed */
#ifndef lint
static char *RCSid = "$Header: /usr/src/local/usr.lib/librmt/RCS/rmtlib.c,v 1.7 89/03/23 14:09:51 root Exp Locker: root $";
#endif
/*
* $Log: rmtlib.c,v $
* Revision 1.7 89/03/23 14:09:51 root
* Fix from haynes@ucscc.ucsc.edu for use w/compat. ADR.
*
* Revision 1.6 88/10/25 17:04:29 root
* rexec code and a bug fix from srs!dan, miscellanious cleanup. ADR.
*
* Revision 1.5 88/10/25 16:30:17 root
* Fix from jeff@gatech.edu for getting user@host:dev right. ADR.
*
* Revision 1.4 87/10/30 10:36:12 root
* Made 4.2 syntax a compile time option. ADR.
*
* Revision 1.3 87/04/22 11:16:48 root
* Two fixes from parmelee@wayback.cs.cornell.edu to correctly
* do fd biasing and rmt protocol on 'S' command. ADR.
*
* Revision 1.2 86/10/09 16:38:53 root
* Changed to reflect 4.3BSD rcp syntax. ADR.
*
* Revision 1.1 86/10/09 16:17:35 root
* Initial revision
*
*/
/*
* rmt --- remote tape emulator subroutines
*
* Originally written by Jeff Lee, modified some by Arnold Robbins
*
* WARNING: The man page rmt(8) for /etc/rmt documents the remote mag
* tape protocol which rdump and rrestore use. Unfortunately, the man
* page is *WRONG*. The author of the routines I'm including originally
* wrote his code just based on the man page, and it didn't work, so he
* went to the rdump source to figure out why. The only thing he had to
* change was to check for the 'F' return code in addition to the 'E',
* and to separate the various arguments with \n instead of a space. I
* personally don't think that this is much of a problem, but I wanted to
* point it out.
* -- Arnold Robbins
*
* Redone as a library that can replace open, read, write, etc, by
* Fred Fish, with some additional work by Arnold Robbins.
*/
/* Use -DUSE_REXEC for rexec code, courtesy of Dan Kegel, srs!dan */
#if defined(USG) && !defined(HAVE_MTIO)
#define NO_RMTIOCTL
#endif
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#ifndef NO_RMTIOCTL
#include <sys/ioctl.h>
#include <sys/mtio.h>
#endif
#ifdef USE_REXEC
#include <netdb.h>
#endif
#include <errno.h>
#include <setjmp.h>
#include <sys/stat.h>
#define BUFMAGIC 64 /* a magic number for buffer sizes */
/*
* MAXUNIT --- Maximum number of remote tape file units
*/
#define MAXUNIT 4
/*
* READ --- Return the number of the read side file descriptor
* WRITE --- Return the number of the write side file descriptor
*/
#define READ(fd) (Ctp[fd][0])
#define WRITE(fd) (Ptc[fd][1])
static int Ctp[MAXUNIT][2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
static int Ptc[MAXUNIT][2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
extern int errno;
char *__rmt_path;
/*
* _rmt_panic --- close off a remote tape connection
*/
static void _rmt_panic(fildes)
int fildes;
{
close(READ(fildes));
close(WRITE(fildes));
READ(fildes) = -1;
WRITE(fildes) = -1;
}
/*
* command --- attempt to perform a remote tape command
*/
static int command(fildes, buf)
int fildes;
char *buf;
{
register int blen;
#ifdef SIGNAL_VOID
void (*pstat)();
#else
int (*pstat)();
#endif
/*
* save current pipe status and try to make the request
*/
blen = strlen(buf);
pstat = signal(SIGPIPE, SIG_IGN);
if (write(WRITE(fildes), buf, blen) == blen)
{
signal(SIGPIPE, pstat);
return(0);
}
/*
* something went wrong. close down and go home
*/
signal(SIGPIPE, pstat);
_rmt_panic(fildes);
errno = EIO;
return(-1);
}
/*
* status --- retrieve the status from the pipe
*/
static int status(fildes)
int fildes;
{
int i;
char c, *cp;
char buffer[BUFMAGIC];
/*
* read the reply command line
*/
for (i = 0, cp = buffer; i < BUFMAGIC; i++, cp++)
{
if (read(READ(fildes), cp, 1) != 1)
{
_rmt_panic(fildes);
errno = EIO;
return(-1);
}
if (*cp == '\n')
{
*cp = 0;
break;
}
}
if (i == BUFMAGIC)
{
_rmt_panic(fildes);
errno = EIO;
return(-1);
}
/*
* check the return status
*/
for (cp = buffer; *cp; cp++)
if (*cp != ' ')
break;
if (*cp == 'E' || *cp == 'F')
{
errno = atoi(cp + 1);
while (read(READ(fildes), &c, 1) == 1)
if (c == '\n')
break;
if (*cp == 'F')
_rmt_panic(fildes);
return(-1);
}
/*
* check for mis-synced pipes
*/
if (*cp != 'A')
{
_rmt_panic(fildes);
errno = EIO;
return(-1);
}
return(atoi(cp + 1));
}
#ifdef USE_REXEC
/*
* _rmt_rexec
*
* execute /etc/rmt on a remote system using rexec().
* Return file descriptor of bidirectional socket for stdin and stdout
* If username is NULL, or an empty string, uses current username.
*
* ADR: By default, this code is not used, since it requires that
* the user have a .netrc file in his/her home directory, or that the
* application designer be willing to have rexec prompt for login and
* password info. This may be unacceptable, and .rhosts files for use
* with rsh are much more common on BSD systems.
*/
static int
_rmt_rexec(host, user)
char *host;
char *user; /* may be NULL */
{
struct servent *rexecserv;
int save_stdin = dup(fileno(stdin));
int save_stdout = dup(fileno(stdout));
int tape_fd; /* Return value. */
/*
* When using cpio -o < filename, stdin is no longer the tty.
* But the rexec subroutine reads the login and the passwd on stdin,
* to allow remote execution of the command.
* So, reopen stdin and stdout on /dev/tty before the rexec and
* give them back their original value after.
*/
if (freopen("/dev/tty", "r", stdin) == NULL)
freopen("/dev/null", "r", stdin);
if (freopen("/dev/tty", "w", stdout) == NULL)
freopen("/dev/null", "w", stdout);
rexecserv = getservbyname("exec", "tcp");
if (NULL == rexecserv) {
fprintf (stderr, "? exec/tcp: service not available.");
exit (-1);
}
if ((user != NULL) && *user == '\0')
user = (char *) NULL;
tape_fd = rexec (&host, rexecserv->s_port, user, NULL,
"/etc/rmt", (int *)NULL);
fclose(stdin);
fdopen(save_stdin, "r");
fclose(stdout);
fdopen(save_stdout, "w");
return tape_fd;
}
#endif /* USE_REXEC */
/*
* _rmt_open --- open a magtape device on system specified, as given user
*
* file name has the form [user@]system:/dev/????
#ifdef COMPAT
* file name has the form system[.user]:/dev/????
#endif
*/
#define MAXHOSTLEN 257 /* BSD allows very long host names... */
int __rmt_open (path, oflag, mode, bias)
char *path;
int oflag;
int mode;
int bias;
{
int i, rc;
char buffer[BUFMAGIC];
char system[MAXHOSTLEN];
char device[BUFMAGIC];
char login[BUFMAGIC];
char *sys, *dev, *user;
sys = system;
dev = device;
user = login;
/*
* first, find an open pair of file descriptors
*/
for (i = 0; i < MAXUNIT; i++)
if (READ(i) == -1 && WRITE(i) == -1)
break;
if (i == MAXUNIT)
{
errno = EMFILE;
return(-1);
}
/*
* pull apart system and device, and optional user
* don't munge original string
* if COMPAT is defined, also handle old (4.2) style person.site notation.
*/
while (*path != '@'
#ifdef COMPAT
&& *path != '.'
#endif
&& *path != ':') {
*sys++ = *path++;
}
*sys = '\0';
path++;
if (*(path - 1) == '@')
{
(void) strcpy (user, system); /* saw user part of user@host */
sys = system; /* start over */
while (*path != ':') {
*sys++ = *path++;
}
*sys = '\0';
path++;
}
#ifdef COMPAT
else if (*(path - 1) == '.')
{
while (*path != ':') {
*user++ = *path++;
}
*user = '\0';
path++;
}
#en